var Chart = function() {
    var _self = this;
    _self.draw = function(options) {
        var domElement = options.domElement;
        var yAxisDots = options.yAxisDots;
        var chartData = options.chartData;
        var refresh = options.refresh;
        var max = yAxisDots[yAxisDots.length - 1];
        var dataCount = jsonLength(chartData);
        var barWidth = (100 / (2 * dataCount - 1));
        
        if (!refresh) {
            //draw vertical lines
            domElement.addClass("chart");
            for (var i = 0; i < dataCount; i++) {
                var left = 2 * barWidth * i + barWidth / 2;
                //domElement.append("<div class='vgl' style='left:" + left + "%'></div>");
                var left = 2 * barWidth * i + barWidth;
                //domElement.append("<div class='vgl strong' style='left:" + left + "%'></div>");
            }
            //draw horizontal lines
            for (var i = 0; i < yAxisDots.length; i++) {
                var bottom = (i + 1) * (100 / yAxisDots.length);
                domElement.append("<div class='hgl' style='bottom:" + bottom + "%'></div>");
                domElement.append("<div class='label y' style='bottom:" + bottom + "%'>" + yAxisDots[i] + "</div>");
            }
        } else {
            domElement.find(".bar").remove();
            domElement.find(".label.x").remove();
        }
        //draw bars
        var k = 0;
        $.each(chartData, function(key, value) {
            var left = 2 * barWidth * k;
            var height = (parseInt(value) * 100) / max;
            domElement.append("<div class='bar " + key + "' data-info='" + key + ": " + value + "' style='left:" + left + "%; height:" + height + "%; width:" + barWidth + "%;'></div>");
            domElement.append("<div class='label x' style='left:" + left + "%; width:" + barWidth + "%;'>" + key + "</div>");
            k += 1;
        });


        //add mouse event handlers (to show data in tooltip)
        var show = false;
        domElement.find(".bar").mouseenter(function(e) {
            show = true;
            var html = "<div class='tooltip' style='top: " + e.pageY + "px; left: " + (e.pageX + 20) + "px;'>" + $(this).data('info') + "</div>";
            $("body").append(html);
        });
        domElement.find(".bar").mousemove(function(e) {
            if (show) {
                $(".tooltip").css("top", e.pageY).css("left", e.pageX + 20);
            }
        });
        domElement.find(".bar").mouseout(function(e) {
            show = false;
            $(".tooltip").remove();
        });
    };

    _self.drawGant = function(options) {
        
        var domElement = options.domElement;
        var yAxisDots = options.yAxisDots;
        var xAxisDots = _self.getXAxisDots({startTime : options.startDate, endTime : options.endDate});
        var chartData = options.chartData;

        domElement.empty();

        var xAxisStartTimeMilis = xAxisDots[0].milis;
        var xAxisEndTimeMilis = xAxisDots[xAxisDots.length - 1].milis;
        var xAxisFullInMilis = xAxisEndTimeMilis - xAxisStartTimeMilis;
        var yAxisPartHeight = 100 / yAxisDots.length;

        domElement.addClass("chart");
        //draw vertical lines
        for (var i = 0; i < xAxisDots.length; i++) {
            //var left = i * (100 / (xAxisDots.length - 1));
            var left = ((xAxisDots[i].milis - xAxisStartTimeMilis) * 100) / xAxisFullInMilis;
            var leftShadow = (left === 0) ? left : left - 5;
            //domElement.append("<div class='vgl strong' style='left:" + left + "%'></div>");
            domElement.append("<div class='vgl' style='left:" + leftShadow + "%'></div>");
            domElement.append("<div class='label x' style='left:" + left + "%'>" + xAxisDots[i].display + "</div>");
        }
        //draw horizontal lines
        for (var i = 0; i < yAxisDots.length; i++) {
            var bottom = (i + 1) * (100 / yAxisDots.length);
            domElement.append("<div class='hgl' style='bottom:" + bottom + "%'></div>");
            domElement.append("<div class='label y' style='bottom:" + bottom + "%'>" + yAxisDots[i] + "</div>");
        }
        //draw bars

        $.each(chartData.items, function(key, value) {
            var startTimeMilis = getTimeFromString(value.startTime);
            var endTimeMilis = getTimeFromString(value.endTime);
            var widthInMilis = endTimeMilis - startTimeMilis;

            var width = (widthInMilis * 100) / xAxisFullInMilis;
            var height = yAxisPartHeight;
            var bottom = (yAxisDots.indexOf(parseInt(value.verticalClass))) * yAxisPartHeight;
            var left = ((startTimeMilis - xAxisStartTimeMilis) * 100) / xAxisFullInMilis;

            var extraClass = value.extraClass ? value.extraClass : "";
            var content = value.description + "<br>" + value.startTime + " - " + value.endTime;
            domElement.append("<div data-info='" + content +"' class='bar " + extraClass + "' style='left:" + left + "%; height:" + height + "%; width:" + width + "%; bottom:" + bottom + "%;'>" + content + "</div>");
        });

        //add mouse event handlers (to show data in tooltip)
        var show = false;
        domElement.find(".bar").mouseenter(function(e) {
            show = true;
            var html = "<div class='tooltip' style='top: " + e.pageY + "px; left: " + (e.pageX + 20) + "px;'>" + $(this).data('info') + "</div>";
            $("body").append(html);
        });
        domElement.find(".bar").mousemove(function(e) {
            if (show) {
                $(".tooltip").css("top", e.pageY).css("left", e.pageX + 20);
            }
        });
        domElement.find(".bar").mouseout(function(e) {
            show = false;
            $(".tooltip").remove();
        });
    };
    _self.prepareAndDrawGant = function(params, domElementHook){
        var chartData = {
            items: []
        };
        var yAxisDots = [];

        $.getJSON(window.CONSTANTS.SERVICE_URL, params, function(data) {
            var datesArray = [];
            $.each(data, function(key, value) {
                addUniqueElement(yAxisDots, parseInt(value.Line));
                var x = {
                    verticalClass: value.Line,
                    description: value.Description,
                    extraClass: window.chart.getRandomClass(),
                    startTime: value.StartTime,
                    endTime: value.EndTime
                };
                chartData.items.push(x);
            });
            var interval = _self.getDateInterval(params);
            var chartParams = {
                domElement: $(domElementHook),
                yAxisDots: yAxisDots.sort(),
                startDate: {
                    date : parseInt(interval.start.split(".")[0]), 
                    month : parseInt(interval.start.split(".")[1]), 
                    year : parseInt(interval.start.split(".")[2])
                },
                endDate: {
                    date : parseInt(interval.end.split(".")[0]),
                    month : parseInt(interval.end.split(".")[1]),
                    year : parseInt(interval.end.split(".")[2])
                },
                chartData: chartData
            };
            _self.drawGant(chartParams);
        });
    };
    _self.getDateInterval = function(params){
        var start, end;
        if(params.timeFrame === "month"){
            var year = params.mYear;
            var monthName = params.mMonth;
            var endDay = _self.getMonthDaysCount(monthName, year);
            start = "1."+_self.getMonthOrd(monthName)+"."+year+".";
            end = "1."+(_self.getMonthOrd(monthName)+1)+"."+year+".";
        }
        else if(params.timeFrame === "period"){
            start = params.pStart;
            end = params.pEnd;
            if(params.pOneDay){
                end = start;
            }
        }
        return {
            start : start,
            end : end
        };
    };
    _self.getXAxisDots = function(options){
        var ret;
        var startTime = options.startTime;
        var endTime = options.endTime;
        var startTimeMilis = _self.getMilisFromDateStrings(startTime, "00:00").milis;
        var endTimeMilis = _self.getMilisFromDateStrings(endTime, "00:00").milis;
        if((endTimeMilis - startTimeMilis) <= 24*60*60*1000){
            ret = [
                { milis : startTimeMilis, display : _self.getDateDisplay(startTimeMilis) },
                _self.getMilisFromDateStrings(startTime, "04:00"),
                _self.getMilisFromDateStrings(startTime, "08:00"),
                _self.getMilisFromDateStrings(startTime, "12:00"),
                _self.getMilisFromDateStrings(startTime, "16:00"),
                _self.getMilisFromDateStrings(startTime, "20:00"),
                { milis : startTimeMilis+24*60*60*1000, display : _self.getDateDisplay(startTimeMilis+24*60*60*1000) }
            ];
        }
        else if((endTimeMilis - startTimeMilis) > 24*60*60*1000 && (endTimeMilis - startTimeMilis) <= 2*24*60*60*1000) {
            ret = [
                { milis : startTimeMilis, display : _self.getDateDisplay(startTimeMilis) },
                _self.getMilisFromDateStrings(startTime, "08:00"),
                _self.getMilisFromDateStrings(startTime, "16:00"),
                { milis : startTimeMilis+24*60*60*1000, display : _self.getDateDisplay(startTimeMilis+24*60*60*1000) },
                _self.getMilisFromDateStrings(startTime, "08:00", {dateOffset : 1}),
                _self.getMilisFromDateStrings(startTime, "16:00", {dateOffset : 1}),
                { milis : startTimeMilis+2*24*60*60*1000, display : _self.getDateDisplay(startTimeMilis+2*24*60*60*1000) }
            ];
        }
        else{
            var x1 = startTimeMilis + Math.round((endTimeMilis - startTimeMilis)*0.25);
            var x2 = startTimeMilis + Math.round((endTimeMilis - startTimeMilis)*0.5);
            var x3 = startTimeMilis + Math.round((endTimeMilis - startTimeMilis)*0.75);
            ret = [
                { 
                    milis : startTimeMilis, 
                    display: _self.getTimeStampDisplay(startTimeMilis) 
                },
                { 
                    milis : x1, 
                    display: _self.getTimeStampDisplay(x1) 
                },
                { 
                    milis : x2, 
                    display: _self.getTimeStampDisplay(x2) 
                },
                { 
                    milis : x3, 
                    display: _self.getTimeStampDisplay(x3) 
                },
                { 
                    milis : endTimeMilis, 
                    display: _self.getTimeStampDisplay(endTimeMilis) 
                },
            ]
        }
        return ret;
    };
    _self.getDateDisplay = function(milis){
        var date = new Date(milis);
        var ret = date.getDate() + ". " + _self.getMonthName(date.getMonth()) + " " + date.getFullYear() + ".";
        return ret;
    };
    _self.getTimeStampDisplay = function(milis){
        var date = new Date(milis);
        var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
        var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
        var ret = date.getDate() + ". " + _self.getMonthName(date.getMonth()) + " " + date.getFullYear() + "." + " " + hours + ":" + minutes;
        return ret;
    };
    _self.getMonthName = function(monthNumber){
        switch(monthNumber){
            case 0 : return "Jan";
            case 1 : return "Feb";
            case 2 : return "Mar";
            case 3 : return "Apr";
            case 4 : return "May";
            case 5 : return "Jun";
            case 6 : return "Jul";
            case 7 : return "Aug";
            case 8 : return "Sep";
            case 9 : return "Oct";
            case 10 : return "Nov";
            case 11 : return "Dec";
        }
    };
    _self.getMonthOrd = function(monthName){
        switch(monthName){
            case "Jan" : return 1;
            case "Feb" : return 2;
            case "Mar" : return 3;
            case "Apr" : return 4;
            case "May" : return 5;
            case "Jun" : return 6;
            case "Jul" : return 7;
            case "Aug" : return 8;
            case "Sep" : return 9;
            case "Oct" : return 10;
            case "Nov" : return 11;
            case "Dec" : return 12;
        }
    };
    _self.getMonthDaysCount = function(monthName, year){
        var extraDay = 0;
        if(year % 4 === 0){
            extraDay = 1;
        }
        switch(monthName){
            case "Jan" : return 31;
            case "Feb" : return 28 + extraDay;
            case "Mar" : return 31;
            case "Apr" : return 30;
            case "May" : return 31;
            case "Jun" : return 30;
            case "Jul" : return 31;
            case "Aug" : return 31;
            case "Sep" : return 30;
            case "Oct" : return 31;
            case "Nov" : return 30;
            case "Dec" : return 31;
        }
    };
    _self.getRandomClass = function(){
        var x = parseInt(Math.random()*3)+1;
        return "class_"+x;
    };
    _self.getMilisFromDateStrings = function(dateJSON, timeStr, options){
        var dateOffset = 0;
        if(options && options.dateOffset){
            dateOffset = options.dateOffset;
        }
        var ret = new Date();
        ret.setYear(dateJSON.year);
        ret.setMonth(dateJSON.month - 1);
        ret.setDate(dateJSON.date);
        ret.setHours(timeStr.split(":")[0]);
        ret.setMinutes(timeStr.split(":")[1]);
        return {
            milis : ret.getTime() + dateOffset*24*60*60*1000,
            display: timeStr
        };
    };
};


